home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
graphic
/
cheetah.zip
/
CGETZP.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-08-21
|
9KB
|
262 lines
/* cgetzp.c
*
* CHAINED mode version.
* NOTE that in this mode BPERROW is a permanent constant, and always equal to
* BPERROW_CHAINED.
*
* Description:
* Get screen image and encode it to ZPacked format.
* Uses the coding method, described in mputz4p.c
*
* Function list:
* CgetZPacked().
*
* Portability: BORLANDC
* (c) erdy 1992
* $Header: $
*/
#pragma inline
#include <limits.h>
#include <alloc.h> /* farcoreleft() */
#include "far.h"
#include "vgaprefx.h"
#include "vgadrv.h"
#include "screen.h"
#include "mxcpy.h"
/* Locals: */
/*void near pascal stringstore(void);*/
#define checkempty() \
asm mov ax, di;\
asm dec ax;\
if (_AX == _BX) {\
/* Counter has been prepared, but hasn't been used.\
* So un-prepare it.\
*/\
asm mov di, bx; /* Decrease pointer */\
asm dec dx; /* Discount data byte */\
}
#define stringstore() {\
asm push ax; /* Save ax */\
checkempty();\
asm xor al, al;\
asm stosb; /* Store 0 */\
asm mov al, cl; /* Put counter to al */\
asm stosb; /* Store counter */\
asm pop ax; /* Restore ax, ah must be kept */\
asm stosb; /* Store color from al, now we can destroy al */\
/* Prepare new counter */\
asm mov bx, di; /* New counter pointer */\
asm xor al, al; /* Zero counter */\
asm stosb; /* Store new counter */\
asm add dx, 4; /* Count the data bytes */\
asm xor cx, cx; /* Clear the counter */\
}
#define skipstore() {\
asm push ax; /* Save ax */\
checkempty();\
asm mov al, cl; /* Put counter to al */\
asm neg al; /* Invert it */\
asm stosb; /* Store counter */\
asm pop ax; /* Restore ax, ah must be kept */\
/* Prepare new counter */\
asm mov bx, di; /* New counter pointer */\
asm xor al, al; /* Zero counter */\
asm stosb; /* Store new counter */\
asm inc dx;\
asm inc dx; /* Count the data bytes */\
asm xor cx, cx; /* Clear the counter */\
}
#define checkfull(n) \
asm push ax; /* Save ax */\
asm mov al, es:[bx]; /* Get counter value */\
if (_AL >= (SCHAR_MAX-n)) { /* Prepare new counter */\
asm mov bx, di;\
asm xor al, al;\
asm stosb; /* Store 0 */\
asm inc dx; /* Count data byte */\
}\
asm pop ax;
Image far *CgetZPacked(unsigned int x, unsigned int y,
unsigned int nc, unsigned int nr,
int backcolor)
{
char far *p;
Image far *ip;
auto unsigned int sz;
auto unsigned long coreleft;
auto int col;
auto int row;
auto union bw {
unsigned char b[2];
int w;
} bc;
bc.w = backcolor;
if ((coreleft = (unsigned long)(nc + nc/2) * nr) > UINT_MAX)
sz = UINT_MAX;
else
sz = coreleft;
if ((coreleft = farcoreleft()/2) > UINT_MAX)
coreleft = UINT_MAX;
if (sz > coreleft)
coreleft = sz;
coreleft -= 16;
If_Overflow:
if ((p = getmem(sz)) == NULL) {
Abort:
scerror = ER_OUTOFMEM;
return(NULL);
}
sz -= 16;
_SI = VIDEO_ADDRESS(x, y); /* Will keep video RAM offset */
asm cld;
asm push ds;
asm les di, p; /* Load data address */
_AX = Scdraw_seg; /* Load video address */
_DS = _AX;
asm xor dx, dx; /* Clear the used space counter */
/* Registers on entrance:
* dx - counter of used space
* es - data segment, di - data offset
* ds - video ram segment, si - video ram offset
*/
for (row = nr; --row >= 0;) {
asm push si; /* Save offset of 1st scanned pixel */
asm xor cx, cx; /* Set the color counter */
asm mov ax, nc;
asm mov col, ax;
asm mov bx, di; /* Save 1st counter pointer */
asm xor al, al;
asm stosb; /* Prepare 1st counter */
asm inc dx; /* Count byte */
asm lodsb; /* Load first pixel */
asm mov ah, al; /* It will be old color */
goto EndLoop;
/*for (col = ncols; --col >= 0;) {*/
LineLoop:
if (_DX >= sz) { /* Out of space ? */
asm pop si;
asm pop ds;
retmem(p);
if (sz == coreleft)
goto Abort;
sz = coreleft+16;
goto If_Overflow;
}
if (col != 0) { /* Not a last pixel */
asm lodsb; /* Load color at ds:[si], advance si */
if (_AL == _AH) { /* The same color ? */
asm inc cx; /* Count this pixel */
/* Not count the 1st pixel, because of flushing */
if (_CX >= SCHAR_MAX) {
if ((bc.b[1]==0) && (bc.b[0]==_AL)) {
skipstore();
}
else if (_CX >= UCHAR_MAX) {
stringstore();
}
}
goto EndLoop;
}
}
else if ((bc.b[1]==0) && (bc.b[0] == _AH)) {
/* Don't flush trailing transparent */
goto OutLoop;
}
/*
* Store pixel literally.
*/
asm xchg ah, al;
/*
* al now contains previous color,
* ah contains new color.
*/
if (_CX != 0) { /* Need to flush string */
asm inc cx; /* Count 1st pixel */
if ((bc.b[1]==0) && (bc.b[0]==_AL)) {
skipstore();
}
else if (_CX > 3) {
stringstore();
}
else {
checkfull(3);
asm add es:[bx], cl; /* Increase counter */
asm add dx, cx;
asm rep stosb;
}
goto EndLoop;
}
if ( ((bc.b[1]==0) && (bc.b[0]==_AL)) ) {
/* Transparent color is always encoding
* in string form.
*/
asm inc cx;
skipstore();
goto EndLoop;
}
checkfull(0);
asm inc byte ptr es:[bx]; /* Increase counter */
asm stosb; /* Store value */
asm inc dx; /* Count data byte */
/*goto EndLoop;*/
/*}*/
EndLoop:
asm dec word pt